package org.massmoderation.com.managers;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.massmoderation.com.config.ConfConstants;
import org.massmoderation.com.config.Configuration;


//TODO kc+kp=100 da fare quando carico le configurations

public class KarmaCalculator extends Connectable
{
	private Integer timeLimitData;
    private double kc;
    private double kp;
		
	private ResultSet rset_calc;
    
	
	
	public KarmaCalculator()
	{
		super();
		timeLimitData=Integer.valueOf(Configuration.getParameter(ConfConstants.TIME_LIMIT_DATA));
	    kc = Double.valueOf(Configuration.getParameter(ConfConstants.KC));
	    kp = Double.valueOf(Configuration.getParameter(ConfConstants.KP));
			    
		rset_calc=null;
		
	}
	
	
	
	/**
	 * Calculates karma for all the users present in Mass Moderation tables. 
	 * Recommended to use it on a daily routine
	 *
	 *	
	             
	@return a boolean that indicates if the method has succeded
	 *  
	
	@author Alessandro Massa
	                          
	 */
	//Calcolo del karma per ogni utente, da eseguire ad ogni intervallo di tempo T
	//Prima di eseguire questo metodo accertati di aver eseguito i metodi per il calcolo dei rating
	//Di tutti i RUC e LUC
	public boolean calculateKarmaForAlls()
	{
		openConnection();
		String query = "SELECT id FROM user";
		rset=doExecQuery(query);
		int id;

		try
		{
			while(rset.next())
			{
				id=rset.getInt("id");
				calculateKarmaById(id);
			}
			con.setAutoCommit(true);
			closeConnection();
			return true;
		}
		catch(SQLException e)
		{
			e.printStackTrace();
			closeConnection();
			return false;
		}

	}
	
	
	
	
	
	/**
	 * Calculates karma for a single user. Mainly used from 'calculateKarmaForAlls'.
	 *
	 *	
	
	@param userId target of the karma calculator             
	             
	@return a boolean that indicates if the method has succeded
	 *  
	
	@author Alessandro Massa
	                          
	 */
	//Metodo per singolo utente
	public boolean calculateKarmaById(Integer userId)
	{		
	    double ncomment_vote=0;
	    double npoi_vote=0;
	    double sum_comment=0;
	    double sum_poi=0;
	    double spc=0;
	    double spp=0;
	    double karma=0d;
	    
	    
	    String query="";
	    //Devo ottenere il numero di tutti i poi che hanno almeno un voto entro gli N giorni decisi
	    //Ovvero, che hanno un rating!=0
	    query="SELECT count(*) FROM poi where creator={user_id} AND rating<>0 AND date>'{timeLimit}'"
	    	.replace("{timeLimit}", getPastDate(timeLimitData))
    		.replace("{user_id}",String.valueOf(userId));
 
	    rset_calc=doExecQuery(query);
    	
	    try
	    {  
	    	rset_calc.next();
	    	npoi_vote=rset_calc.getInt("count(*)");
	    	
	    	if(npoi_vote!=0)
	    	{
		    	//Ottengo la somma del punteggio di tutti i Poi dell'utente
		    	query="select SUM(rating) from poi where creator={user_id} AND date>'{timeLimit}'"
		    	    .replace("{timeLimit}", getPastDate(timeLimitData))
		    		.replace("{user_id}", String.valueOf(userId));
		    	rset_calc=doExecQuery(query);
		    		    	
		    	rset_calc.next();
		    	
		    	sum_poi=rset_calc.getDouble("SUM(rating)");
		    	}
	    	else
	    		sum_poi=0;

	    	
	    	
		    //Devo ottenere il numero di tutti i commenti che hanno almeno un voto entro gli N giorni decisi
		    //Ovvero, che hanno un rating!=0
	    	query="SELECT count(*) FROM comment where creator={user_id} AND rating<>0 AND date>'{timeLimit}'"
	    	    	.replace("{timeLimit}", getPastDate(timeLimitData))
	    			.replace("{user_id}",String.valueOf(userId));
	    	rset_calc=doExecQuery(query);
	
	    		    	
	    	rset_calc.next();
	    	ncomment_vote=rset_calc.getInt("count(*)");
	    	
	    	if(ncomment_vote!=0)
	    	{
		    	//Ottengo la somma del punteggio di tutti i Poi dell'utente
		    	query="select SUM(rating) from comment where creator={user_id} AND date>'{timeLimit}'"
		    	    	.replace("{timeLimit}", getPastDate(timeLimitData))
		    			.replace("{user_id}", String.valueOf(userId));
		    	rset_calc=doExecQuery(query);
		    		    	
		    	rset_calc.next();
		    	
		    	sum_comment=rset_calc.getDouble("SUM(rating)");
	    	}
	    	else
	    		sum_comment=0;
	    	
	    	//Ottengo il punteggio pesato di poi e commenti
	    	
	    	if(ncomment_vote!=0)
	    		spc=(kc/ncomment_vote) * sum_comment;
	    	else
	    		spc=0;
	    	
	    	if(npoi_vote!=0)
	    		spp=(kp/npoi_vote) * sum_poi;
	    	else
	    		spp=0;
	    	
	    	karma=spc+spp;
	    	
			query = "UPDATE user SET karma={karma} WHERE id={user_id}"
				.replace("{karma}", String.valueOf(karma))
				.replace("{user_id}", String.valueOf(userId));
	    				
			doUpdateQuery(query);
	    	
	    	System.out.println("Calcolato il karma per l'user id n " + userId);
		    	
		    			
			return true;
	    }
	    catch(SQLException e)
	    {
	    	e.printStackTrace();
			closeConnection();
	    	return false;
	    }
	}

	
	
	/**
	 * Override of the super.closeConnection() (needed because of other fields 
	 * specifics of this class)
	 *
	 *  
	
	@author Alessandro Massa
	                          
	 */
	//Override del metodo del padre che concatena alla vecchia closeConnection le 
	//nuove variabili di connessione dichiarate in questa classe
	protected void closeConnection()
	{

		try { rset_calc.close();} catch (Exception e) {}	
		super.closeConnection();
	}
	
	
	
	
	/**
	 * Returns a "yyyy-MM-dd HH:mm:ss" date formatted of n days ago.
	 *
	 *
	@param	n	number of days ago

	             
	@return date formatted in "yyyy-MM-dd HH:mm:ss"
	 *  
	
	@author Alessandro Massa
	                          
	 */
	//Restituisce la data di ieri in formato "yyyy-MM-dd HH:mm:ss"
	private String getPastDate(Integer n)
	{
		
		
        Calendar cal = Calendar.getInstance();  
        cal.add(Calendar.DATE, -n);  
        Date date =cal.getTime();
        String pastDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        
		return pastDate;
	}
	
	
}
